package java_option.audio;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

import java_option.audio.config.AudioConfig;

/**
 * 默认wav文件采用littleEndian存储data数据的
 * 
 * @author java红了 | java_option <br>
 *         2020-11-419:14:04
 */
public class SpeechStore {

	private static byte[] RIFF = "RIFF".getBytes();
	private static byte[] RIFF_SIZE = new byte[4]; //
	private static byte[] RIFF_TYPE = "WAVE".getBytes();

	private static byte[] FORMAT = "fmt ".getBytes();
//
//
//
	private static byte[] FORMAT_SIZE = new byte[4];
	private static byte[] FORMATTAG = new byte[2]; //
	private static byte[] CHANNELS = new byte[2]; //
	private static byte[] SamplesPerSec = new byte[4]; //
	private static byte[] AvgBytesPerSec = new byte[4]; //
	private static byte[] BlockAlign = new byte[2]; //
	private static byte[] BitsPerSample = new byte[2]; //

	private static byte[] DataChunkID = "data".getBytes();
	private static byte[] DataSize = new byte[4];
	public static boolean isrecording = false;

	public void writeToWave() {
		init();
	}

	public static void init() {
//

		FORMAT_SIZE = new byte[] { (byte) 16, (byte) 0, (byte) 0, (byte) 0 };
		byte[] tmp = revers(intToBytes(1));
		FORMATTAG = new byte[] { tmp[0], tmp[1] };
		tmp = revers(intToBytes(AudioConfig.channels));
		CHANNELS = new byte[] { tmp[0], tmp[1] };
		SamplesPerSec = revers(intToBytes(AudioConfig.sampleRate));
		int bytePerSec = AudioConfig.sampleRate * AudioConfig.channels * AudioConfig.sampleSizeInBits / 8;
		AvgBytesPerSec = revers(intToBytes(bytePerSec));//
		int blockAlign = AudioConfig.channels * AudioConfig.sampleSizeInBits / 8;
		tmp = revers(intToBytes(blockAlign));//
		BlockAlign = new byte[] { tmp[0], tmp[1] }; //
		tmp = revers(intToBytes(AudioConfig.sampleSizeInBits));
		BitsPerSample = new byte[] { tmp[0], tmp[1] };
	}

	public static byte[] revers(byte[] tmp) {
		byte[] reversed = new byte[tmp.length];
		for (int i = 0; i < tmp.length; i++) {
			reversed[i] = tmp[tmp.length - i - 1];
		}
		return reversed;
	}

	public static byte[] intToBytes(int num) {
		byte[] bytes = new byte[4];
		bytes[0] = (byte) (num >> 24);
		bytes[1] = (byte) ((num >> 16) & 0x000000FF);
		bytes[2] = (byte) ((num >> 8) & 0x000000FF);
		bytes[3] = (byte) (num & 0x000000FF);
		return bytes;

	}

	private File wavFile = new File(AudioConfig.wavDir, System.currentTimeMillis() + ".wav");

	public void writeToWaveFile(byte[] data, boolean append, boolean isBigEndian) {
		RandomAccessFile acf = null;
		try {
			acf = new RandomAccessFile(wavFile, "rw");
//
			if (acf.length() <= 44) {
				int length = data.length;
				DataSize = revers(intToBytes(length));
//
//
				RIFF_SIZE = revers(intToBytes(length + 8 + 24 + (12 - 8)));

//
				acf.write(RIFF);
				acf.write(RIFF_SIZE);
				acf.write(RIFF_TYPE);

//
				acf.write(FORMAT);
				acf.write(FORMAT_SIZE);
				acf.write(FORMATTAG);
				acf.write(CHANNELS);
				acf.write(SamplesPerSec);
				acf.write(AvgBytesPerSec);
				acf.write(BlockAlign);
				acf.write(BitsPerSample);

//
				acf.write(DataChunkID);
				acf.write(DataSize);

			} else {
				int length = (int) acf.length() + data.length;
//
				DataSize = revers(intToBytes(length - 12 - 24 - 8));
//
//
				RIFF_SIZE = revers(intToBytes(length - 8));
//
				acf.seek(4);
				acf.write(RIFF_SIZE);
//
				acf.seek(40);
				acf.write(DataSize);

//
				acf.seek(acf.length()); //
			}
//
			if (isBigEndian == false) {
				acf.write(data);
			} else {
//
				int blockAlign = AudioConfig.channels * AudioConfig.sampleSizeInBits / 8;

				int size = data.length / blockAlign;
				for (int i = 0; i < size; i++) {
//
					byte[] data4 = Arrays.copyOfRange(data, i * blockAlign, (i + 1) * blockAlign);
//
//
//
					byte[] little4 = revers(data4);
					acf.write(little4);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				acf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}
